package com.x.uikit.page;

import android.util.Log;

import androidx.annotation.NonNull;

public class XLifecycle {
    public enum State {INIT, CREATE, START, RESUME, PAUSE, STOP, DESTROY}

    private final StrongListeners<XLifecycleListener> mStrongListeners = new StrongListeners<>();
    private final WeakListeners<XLifecycleListener> mWeakListeners = new WeakListeners<>();
    private State mState = State.INIT;

    public void addObserver(XLifecycleListener observer) {
        mStrongListeners.addListener(observer);
    }

    public void removeObserver(XLifecycleListener observer) {
        mStrongListeners.removeListener(observer);
    }

    public void addWeakObserver(XLifecycleListener observer) {
        mWeakListeners.addListener(observer);
    }

    public void update(State state) {
        if (state == mState) {
            return;
        }
        try {
            onUpdate(mState, state);
            mState = state;
        } catch (Exception e) {
            Log.d("xlifecycle", "update state fail:" + e.getMessage());
        }
    }

    private void onUpdate(State oldState, State newState) throws Exception {
        switch (newState) {
            case INIT:
                break;
            case CREATE:
                if (!contains(oldState, State.INIT, State.DESTROY)) {
                    throw new Exception("can not switch to " + newState + ",because last state is " + oldState);
                }
                create();
                break;
            case START:
                if (!contains(oldState, State.CREATE, State.STOP)) {
                    throw new Exception("can not switch to " + newState + ",because last state is " + oldState);
                }
                start();
                break;
            case RESUME:
                if (!contains(oldState, State.PAUSE)) {
                    throw new Exception("can not switch to " + newState + ",because last state is " + oldState);
                }
                resume();
                break;
            case PAUSE:
                if (!contains(oldState, State.RESUME)) {
                    throw new Exception("can not switch to " + newState + ",because last state is " + oldState);
                }
                pause();
                break;
            case STOP:
                if (!contains(oldState, State.PAUSE, State.START)) {
                    throw new Exception("can not switch to " + newState + ",because last state is " + oldState);
                }
                stop();
                break;
            case DESTROY:
                if (!contains(oldState, State.INIT, State.CREATE, State.STOP)) {
                    throw new Exception("can not switch to " + newState + ",because last state is " + oldState);
                }
                destroy();
                break;
        }
    }

    private boolean contains(State newState, State... states) {
        for (State temp : states) {
            if (newState == temp) {
                return true;
            }
        }
        return false;
    }

    private void create() {
        mStrongListeners.callback(new StrongListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onCreate();
            }
        });
        mWeakListeners.callback(new WeakListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onCreate();
            }
        });
    }

    private void start() {
        mStrongListeners.callback(new StrongListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onStart();
            }
        });
        mWeakListeners.callback(new WeakListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onStart();
            }
        });
    }

    private void resume() {
        mStrongListeners.callback(new StrongListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onResume();
            }
        });
        mWeakListeners.callback(new WeakListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onResume();
            }
        });
    }

    private void pause() {
        mStrongListeners.callback(new StrongListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onPause();
            }
        });
        mWeakListeners.callback(new WeakListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onPause();
            }
        });
    }

    private void stop() {
        mStrongListeners.callback(new StrongListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onStop();
            }
        });
        mWeakListeners.callback(new WeakListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onStop();
            }
        });
    }

    private void destroy() {
        mStrongListeners.callback(new StrongListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onDestroy();
            }
        });
        mWeakListeners.callback(new WeakListeners.ICallbackTask<XLifecycleListener>() {
            @Override
            public void run(@NonNull XLifecycleListener observer) {
                observer.onDestroy();
            }
        });
    }
}
